package ee.az.tetris.worker;

import ee.az.tetris.Dispatcher;
import ee.az.tetris.Glass;
import ee.az.tetris.event.DownEvent;
import ee.az.tetris.event.DownTickEvent;
import ee.az.tetris.event.Event;
import ee.az.tetris.event.FallEndEvent;
import ee.az.tetris.event.FallStartEvent;
import ee.az.tetris.event.FallTickEvent;
import ee.az.tetris.event.FixBlocksEvent;
import java.awt.Color;

/**
 * @author Artur Zinatullin (artur.zinatullin@gmail.com) 2010
 */
public class FallWorker extends Worker {

	private final Dispatcher dispatcher;
	private boolean falling = false;

	public FallWorker(Glass glass, Dispatcher dispatcher) {
		super(glass);
		this.dispatcher = dispatcher;
	}

	@Override
	public void work(Event event) {
		if (event instanceof DownEvent) {
			shiftDown();
		} else if (event instanceof DownTickEvent) {
			shiftDown();
		} else if (event instanceof FallTickEvent && falling) {
			shiftDown();
		} else if (event instanceof FallStartEvent) {
			falling = true;
		} else if (event instanceof FallEndEvent) {
			falling = false;
		}
	}

	private void shiftDown() {
		boolean canFall = true;
		for (int col = 0; col < getGlass().getColumnCount(); col++) {
			for (int row = getGlass().getRowCount()-1; row >= 0 ; row--) {
				Color value = getGlass().getValue(col, row);
				if (Glass.FLOATING.equals(value)) {
					if (!isAvaliable(col, row+1, getGlass())) {
						canFall = false;
					}
				}
			}
		}
		if (canFall) { // then fall
			for (int col = 0; col < getGlass().getColumnCount(); col++) {
				for (int row = getGlass().getRowCount()-1; row >= 0 ; row--) {
					Color value = getGlass().getValue(col, row);
					if (Glass.FLOATING.equals(value)) {
						getGlass().setValue(value, col, row+1);
						getGlass().setValue(Glass.EMPTY, col, row);
					}
				}
			}
		} else { // then fix
			if (!falling) {
				dispatcher.dispatch(new FixBlocksEvent());
			}
			dispatcher.dispatch(new FallEndEvent());
		}
	}
}
